#ifndef CPPAD_CG_SAVE_FILES_MODEL_LIBRARY_PROCESSOR_INCLUDED
#define CPPAD_CG_SAVE_FILES_MODEL_LIBRARY_PROCESSOR_INCLUDED
/* --------------------------------------------------------------------------
 *  CppADCodeGen: C++ Algorithmic Differentiation with Source Code Generation:
 *    Copyright (C) 2019 Joao Leal
 *    Copyright (C) 2013 Ciengis
 *
 *  CppADCodeGen is distributed under multiple licenses:
 *
 *   - Eclipse Public License Version 1.0 (EPL1), and
 *   - GNU General Public License Version 3 (GPL3).
 *
 *  EPL1 terms and conditions can be found in the file "epl-v10.txt", while
 *  terms and conditions for the GPL3 can be found in the file "gpl3.txt".
 * ----------------------------------------------------------------------------
 * Author: Joao Leal
 */

namespace CppAD {
namespace cg {

/**
 * Saves source code generated by a model library source code generator to
 * the file system. This is typically used for debugging purposes.
 * 
 * @author Joao Leal
 */
template<class Base>
class SaveFilesModelLibraryProcessor : public ModelLibraryProcessor<Base> {
public:

    inline explicit SaveFilesModelLibraryProcessor(ModelLibraryCSourceGen<Base>& modelLibraryHelper) :
        ModelLibraryProcessor<Base>(modelLibraryHelper) {
    }

    inline virtual ~SaveFilesModelLibraryProcessor() = default;

    inline void saveSources() {
        saveSourcesTo("cppadcg_sources");
    }

    inline void saveSourcesTo(const std::string& sourcesFolder) {

        auto saveFile = [&](const std::string& filename, const std::string& source){
            std::ofstream sourceFile;
            std::string file = system::createPath(sourcesFolder, filename);
            sourceFile.open(file.c_str());
            sourceFile << source;
            sourceFile.close();
        };

        system::createFolder(sourcesFolder);

        const std::map<std::string, ModelCSourceGen<Base>*>& models = this->modelLibraryHelper_->getModels();

        for (const auto& itm : models) {
            const std::map<std::string, std::string>& sources = this->getSources(*itm.second);

            for (const auto& it : sources) {
                saveFile(it.first, it.second);
            }
        }

        for (const auto& it : this->modelLibraryHelper_->getLibrarySources()) {
            saveFile(it.first, it.second);
        }

        for (const auto& it : this->modelLibraryHelper_->getCustomSources()) {
            saveFile(it.first, it.second);
        }
    }

    inline static void saveLibrarySourcesTo(ModelLibraryCSourceGen<Base>& modelLibraryHelper,
                                            const std::string& sourcesFolder) {
        SaveFilesModelLibraryProcessor s(modelLibraryHelper);
        s.saveSourcesTo(sourcesFolder);
    }

};

} // END cg namespace
} // END CppAD namespace

#endif